package com.zp.mall.product.controller;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.zp.common.valid.AddGroup;
import com.zp.common.valid.UpdateGroup;
import com.zp.common.valid.UpdateStatusGroup;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.zp.mall.product.entity.BrandEntity;
import com.zp.mall.product.service.BrandService;
import com.zp.common.utils.PageUtils;
import com.zp.common.utils.R;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;


/**
 * 品牌
 *
 * @author zhangpeng
 * @email zhangpeng@aliyun.com
 * @date 2020-10-11 17:08:57
 */
/**
 *  1、整合Mybatis-Plus
 *      1）、导入依赖   mybatis-plus-boot-starter
 *      2）、配置
 *          1.配置数据源
 *              1)、导入数据库的驱动
 *              2)、在application.yml中配置数据源的相关信息
 *          2.配置Mybatis-Plus
 *              1)、使用@MapperScan
 *              2)、告诉Mybatis-Plus， sql映射文件位置
 *
 *  2、逻辑删除（详情见mybatis-plus官网：https://baomidou.com/guide/logic-delete.html#%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95%EF%BC%9A）
 *      1）、application.yml配置全局的逻辑删除规则（可省略）
 *      2）、实体类字段上加上@TableLogic注解
 *
 *  3、JSR303完成后端校验
 *      1）给Bean要校验的属性添加校验注解:  javax.validation.constraints包下
 *      2）开启校验功能 @Valid
 *         效果：校验失败后 会有默认的响应
 *     3）给检验Bean后面紧跟一个 BindingResult, 就可以获取到校验的结果
 *     4）分组校验（多场景的复杂校验）
 *          1）、给校验注解标注什么情况下需要进行校验
 *                  @Null(message = "添加的时候品牌ID为空号", groups = {UpdateGroup.class})
 * 	                @NotNull(message = "修改的时候品牌ID不能为空", groups = {AddGroup.class})
 *          2）、校验Controller接收到的实体类时校验不适用JSR303的@Valid  使用Spring提供的@Validated({AddGroup.class}) @Validated可以指定校验的分组是什么
 *          3）、默认没有指定分组的校验注解 @NotBlank , 在分组校验的情况下不会生效 使用@Valid注解进行校验会生效  因为@Valid注解不能指定校验分组
 *          4）、自定义校验
 *              1、编写一个自定义校验注解
 *              2、编写一个自定义校验器
 *              3、将自定的校验器与自定义校验注解进行关联
 *              @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
 *              @Retention(RUNTIME)
 *              @Documented
 *              @Constraint(validatedBy = {ListValsConstraintValidator.class })  //关联  可以指定多个不同的校验，适配不同类型的校验
 * public @interface ListVals {
 *     String message() default "{com.zp.common.valid.ListVals.message}";
 *
 * 	Class<?>[] groups() default { };
 *
 * 	Class<? extends Payload>[] payload() default { };
 *
 * 	int[] vals() default { };
 * }
 *  4、使用@ControllerAdvice 和 @ExceptionHandler 进行全局异常处理
 */
@RestController
@RequestMapping("product/brand")
public class BrandController {
    @Autowired
    private BrandService brandService;

    /**
     * 列表
     */
    @RequestMapping("/list")
    //@RequiresPermissions("product:brand:list")
    public R list(@RequestParam Map<String, Object> params){
        PageUtils page = brandService.queryPage(params);

        return R.ok().put("page", page);
    }


    /**
     * 信息
     */
    @RequestMapping("/info/{brandId}")
    //@RequiresPermissions("product:brand:info")
    public R info(@PathVariable("brandId") Long brandId){
		BrandEntity brand = brandService.getById(brandId);

        return R.ok().put("brand", brand);
    }

    /**
     * 保存
     */
    @RequestMapping("/save")
    //@RequiresPermissions("product:brand:save")
    public R save(@Validated({AddGroup.class}) @RequestBody BrandEntity brand/*, BindingResult bindingResult*/){
        //使用全局统一异常处理参数校验异常
        /*if (bindingResult.hasErrors ()) {
            Map<String, String> map = new HashMap<> ();
            List<FieldError> fieldErrors = bindingResult.getFieldErrors ();
            for (FieldError fieldError : fieldErrors) {
                map.put (fieldError.getField (), fieldError.getDefaultMessage ());
            }
            return R.error (400,"提交的数据不合法").put ("data", map);
        } else {
            brandService.save(brand);
        }*/
        brandService.save(brand);
        return R.ok();
    }

    /**
     * 修改
     * 如果品牌名称修改了
     * 修改其它表与之对应的品牌名称
     */
    @RequestMapping("/update")
    //@RequiresPermissions("product:brand:update")
    public R update(@Validated(UpdateGroup.class) @RequestBody BrandEntity brand){
        brandService.updateBrand(brand);  //修改品牌
        return R.ok();
    }


    /**
     * 修改
     */
    @RequestMapping("/update/status")
    //@RequiresPermissions("product:brand:update")
    public R updateStatus(@Validated(UpdateStatusGroup.class) @RequestBody BrandEntity brand){
		brandService.updateById(brand);

        return R.ok();
    }

    /**
     * 删除
     */
    @RequestMapping("/delete")
    //@RequiresPermissions("product:brand:delete")
    public R delete(@RequestBody Long[] brandIds){
		brandService.removeByIds(Arrays.asList(brandIds));

        return R.ok();
    }

}
